/*

gluetostringc see gluetostring.m

FORMAT:       glued = gluetostring(toglue, glue, endterm);
 
Input fields:
 
      toglue      cell array with snippets
      glue        optional glue string (default: LF)
      endterm     flag, keep end termination

Output fields:
      glued       1xN char array/string with glued content

% Version:  v0.7f
% Build:    8110521
% Date:     Nov-05 2008, 9:00 PM CET
% Author:   Jochen Weber, SCAN Unit, Columbia University, NYC, NY, USA
% URL/Info: http://wiki.brainvoyager.com/BVQXtools

*/

#include "mex.h"
#include "matrix.h"
#include "math.h"
#include <stdio.h>

#define CHAR_LF 10

/* here comes the main function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    mxClassID cid;
    int ne, ncells;
    const int *dim;
    unsigned short *glued, gluechar;
    const unsigned short *toglue;
    const unsigned short *glue;
    const unsigned short defglue[1] = {CHAR_LF};
    const mxArray *snippet, *togluec;
    
    int odim[2] = {1, 0};
    signed long gluelen = 1, copypos = 0, totallen = 0, sc = 0;
    bool endterm = false;
    mxArray *split, *psplit;
    
    
    /* check argument count and content */
	if (nrhs < 1 || nrhs > 3 || nlhs > 1)
		mexErrMsgTxt("Bad number of input/output arguments.");
    if (mxGetClassID(*prhs) != mxCELL_CLASS)
		mexErrMsgTxt("First input must be a cell array.");
    togluec = *prhs;
    ncells = mxGetNumberOfElements(togluec);
    if (ncells == 0) {
        *odim = 0;
        *plhs = mxCreateCharArray(2, odim);
        return;
    }
    glue = defglue;
    if ((nrhs > 1) &&
        (mxGetClassID(prhs[1]) == mxCHAR_CLASS)) {
        dim = mxGetDimensions(prhs[1]);
        if ((dim[1] > 0) &&
            (dim[1] == mxGetNumberOfElements(prhs[1]))) {
            glue = (const unsigned short *) mxGetData(prhs[1]);
            gluelen = dim[1];
        }
    }
    if (nrhs > 2) {
        if ((mxGetClassID(prhs[2]) == mxLOGICAL_CLASS) &&
            (mxGetNumberOfElements(prhs[2]) == 1))
            endterm = (*((unsigned char *) mxGetData(prhs[2])) != 0);
    }
    
    /* count real snippets and length */
    for (; sc < ncells; ++sc) {
        snippet = mxGetCell(togluec, sc);
        if (mxGetClassID(snippet) != mxCHAR_CLASS)
            mexErrMsgTxt("All cells must be of type char.");
        totallen += mxGetNumberOfElements(snippet);
    }
    totallen += gluelen * ((endterm) ? (ncells) : (ncells - 1));
    
    /* create output */
    odim[1] = totallen;
    *plhs = mxCreateCharArray(2, odim);
    glued = (unsigned short *) mxGetData(*plhs);
    
    /* depending on gluelen */
    gluechar = *glue;
    --ncells;
    switch (gluelen) {
        case 0:
            for (sc = 0; sc < ncells; ++sc) {
                snippet = mxGetCell(togluec, sc);
                toglue = (const unsigned short*) mxGetData(snippet);
                ne = mxGetNumberOfElements(snippet);
                for (copypos = ne; copypos > 0; --copypos)
                    *glued++ = *toglue++;
            }
            break;
        case 1:
            for (sc = 0; sc < ncells; ++sc) {
                snippet = mxGetCell(togluec, sc);
                toglue = (const unsigned short*) mxGetData(snippet);
                ne = mxGetNumberOfElements(snippet);
                for (copypos = ne; copypos > 0; --copypos)
                    *glued++ = *toglue++;
                *glued++ = gluechar;
            }
            break;
        case 2:
            for (sc = 0; sc < ncells; ++sc) {
                snippet = mxGetCell(togluec, sc);
                toglue = (const unsigned short*) mxGetData(snippet);
                ne = mxGetNumberOfElements(snippet);
                for (copypos = ne; copypos > 0; --copypos)
                    *glued++ = *toglue++;
                *glued++ = gluechar;
                *glued++ = glue[1];
            }
            break;
        default:
            for (sc = 0; sc < ncells; ++sc) {
                snippet = mxGetCell(togluec, sc);
                toglue = (const unsigned short*) mxGetData(snippet);
                ne = mxGetNumberOfElements(snippet);
                for (copypos = ne; copypos > 0; --copypos)
                    *glued++ = *toglue++;
                *glued++ = gluechar;
                for (copypos = 1; copypos < gluelen; ++copypos)
                    *glued++ = glue[copypos];
            }
            break;
    }
    snippet = mxGetCell(togluec, sc);
    toglue = (const unsigned short*) mxGetData(snippet);
    ne = mxGetNumberOfElements(snippet);
    for (copypos = ne; copypos > 0; --copypos)
        *glued++ = *toglue++;
    if (endterm)
        for (copypos = 0; copypos < gluelen; ++copypos)
            *glued++ = *glue++;
}
